Persistent Lazy Segment Tree
Operations
モノイド$ (M, *)の列$ a_1, a_2, \dots, a_n
作用素としてのモノイド$ (E, \cdot)
作用としての写像$ f: M \times E \rightarrow M
以下を満たす
任意の$ a, b \in M, p \in Eについて$ f(a * b, p) = f(a, p) * f(b, p)
演算後に作用させた結果は, 演算前に作用させた結果に等しい
作用は$ \astに対して分配的
任意の$ a \in M, p, q \in Eについて$ f(f(a, p), q) = f(a, q \cdot p)
二つの作用素を順に作用させた結果は, それらの作用素を先に結合してから作用させた結果に等しい
$ eを$ Eの単位元とすると,任意の$ a \in Mについて $ f(a, e) = a
作用が区間の要素数に比例して変化してもよい
そのときは一番目の条件だけ変化する
$ p \in E, k \in \mathbb{N}について, $ \overbrace{p \cdot \ldots \cdot p}^{k}を$ p^kと表現する
任意の$ a, b \in M, p \in E, k \in \mathbb{N}について$ f(a*b, p^{2k}) = f(a, p^{k}) * f(b, p^{k})
空間計算量$ \Theta(n)
$ \mathtt{new}()
列の項がすべて$ Mの単位元であるLazy Segment Treeを作成する
時間計算量 $ \Theta(n)
$ \mathtt{build}(a_1, a_2, \dots, a_n)
与えられた列を表現するLazy Segment Treeを作成する
時間計算量 $ \Theta(n)
$ \mathtt{effect}(l, r, e)
$ a_l, a_{l+1}, \dots, a_rをそれぞれ$ eによる作用で$ f(a_l, e), f(a_{l+1}, e), \dots, f(a_r, e)にしたLazy Segment Treeを作成する
時間計算量 $ \Omicron(\log n)
$ \mathtt{fold}(l, r)
$ a_l * a_{l+1} * \dots * a_rを計算する
時間計算量 $ \Omicron(\log n)
Summary
Lazy Segment Tree の各ノードには$ Mの値だけでなく, 遅延伝搬する$ Eの値と遅延伝搬する値があるかどうかのtoggleを持つ.
ノードがconstになるため, pushはできない.
再帰的にノードにアクセスする際に, 通ったノードの$ Eの値を結合させていく.
$ \mathtt{effect}(2, 6, p)
https://gyazo.com/440aedcab9497f552e62ed3f1cb3faeb
References
Notes
$ Eの値を結合させるとき順番を間違えやすい
根に近いほうがより新しい作用
Implementations
Problems